package service

import (
	"context"
	"errors"
	"gitee.com/DonHz/basic-go/webook/internal/domain"
	"gitee.com/DonHz/basic-go/webook/internal/repository"
	"gitee.com/DonHz/basic-go/webook/pkg/logger"
	"golang.org/x/crypto/bcrypt"
)

var (
	ErrUserDuplicateEmail = repository.ErrUserDuplicate
    ErrInvalidUserOrPassword = errors.New("账号/邮箱或密码错误")
)

type UserService interface {
	SignUp(ctx context.Context, u domain.User) error
	Login(ctx context.Context, input_u domain.User) (domain.User, error)
	UpdateNonSensitiveInfo(ctx context.Context, user domain.User) error
	FindById(ctx context.Context, Id int64) (domain.User, error)
	FindOrCreate(ctx context.Context, phone string) (domain.User, error)
	FindOrCreateByWechat(ctx context.Context, wechatInfo domain.WechatInfo) (domain.User, error)
	Edit(ctx context.Context) error
	Profile(ctx context.Context, id int64) (domain.User, error)
}

type User_Service struct {
	repo repository.UserRepository
	l logger.Logger
}

func NewUserService(repo repository.UserRepository, l logger.Logger) UserService {
	return &User_Service{
		repo: repo,
		l:l,
	}
}

func (svc *User_Service) SignUp(ctx context.Context, u domain.User) error {
	// 考虑加密放在哪里
	hash, err := bcrypt.GenerateFromPassword([]byte(u.Password), bcrypt.DefaultCost)
	if err != nil {
		return err
	}
	u.Password = string(hash)
	// 存起来
	return svc.repo.Create(ctx, u)
}

func (svc *User_Service) Login(ctx context.Context, input_u domain.User) (domain.User, error) {
	// 先根据账号（邮箱）找用户
	u, err := svc.repo.FindByEmail(ctx, input_u.Email)
	if err == repository.ErrUserNotFound {
		return domain.User{}, ErrInvalidUserOrPassword
	}
	if err != nil {
		return domain.User{}, err
	}
	// 比较密码
	err = bcrypt.CompareHashAndPassword([]byte(u.Password), []byte(input_u.Password))
	if err != nil {
		return domain.User{}, ErrInvalidUserOrPassword
	}
	return u, nil

}
func (svc *User_Service) UpdateNonSensitiveInfo(ctx context.Context, user domain.User) error {
	return svc.repo.UpdateNonZeroFields(ctx, user)
}

func (svc *User_Service) FindById(ctx context.Context, Id int64) (domain.User, error) {
	return svc.repo.FindById(ctx, Id)
}

func (svc *User_Service) FindOrCreate(ctx context.Context, phone string) (domain.User, error) {
	u, err:=svc.repo.FindByPhone(ctx, phone)
	// Find成功或者其他错误
	if err!=repository.ErrUserNotFound{
		svc.l.Info("该手机号已注册", logger.String("phone", phone), logger.String("method", "UserService.FindOrCreate"))
		return u, err
	}
	svc.l.Info("该手机号未注册", logger.String("phone", phone))
	// 需要创建用户
	u = domain.User{
		Phone: phone,
	}
	err=svc.repo.Create(ctx, u)
	if err!=nil && err!=repository.ErrUserDuplicate{
		return u, err
	}
	return svc.repo.FindByPhone(ctx, phone)
}

func (svc *User_Service) FindOrCreateByWechat(ctx context.Context,
	wechatInfo domain.WechatInfo) (domain.User, error){
	u, err:=svc.repo.FindByWechat(ctx, wechatInfo)
	// Find成功或者其他错误
	if err!=repository.ErrUserNotFound{
		return u, err
	}
	// 需要创建用户
	u = domain.User{
		WechatInfo: wechatInfo,
	}
	err=svc.repo.Create(ctx, u)
	if err!=nil && err!=repository.ErrUserDuplicate{
		return u, err
	}
	return svc.repo.FindByWechat(ctx, wechatInfo)
}

func (svc *User_Service) Edit(ctx context.Context) error {
	return nil
}

func (svc *User_Service) Profile(ctx context.Context, id int64) (domain.User, error) {
	// 在系统内部，基本上都用ID
	u, err:=svc.repo.FindById(ctx, id)
	return u, err
}
